package com.sun.common.core.excel.model;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.excel.support.ExcelTypeEnum;

import java.io.OutputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * The type Write meta.
 *
 * @param <T> the type parameter
 * @author : Milo
 */
@SuppressWarnings(SuppressWarningConstant.UNUSED)
public class WriteMeta<T> {
    private OutputStream excelStream;
    private Integer headRowNumber;
    private Class<T> clazz;
    private String password;
    private List<T> data = new ArrayList<>();
    private ExcelTypeEnum type = ExcelTypeEnum.XLSX;
    private String filename = LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss");

    /**
     * Instantiates a new Write meta.
     */
    public WriteMeta() {
    }

    private WriteMeta(final Builder<T> builder) {
        this.excelStream = builder.excelStream;
        this.headRowNumber = builder.headRowNumber;
        this.clazz = builder.clazz;
        this.password = builder.password;
        this.type = builder.type;
        this.filename = builder.filename;
        this.data = builder.data;
    }

    /**
     * Builder builder.
     *
     * @param <T> the type parameter
     * @return the builder
     */
    public static <T> Builder<T> builder() {
        return new Builder<>();
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.excelStream, this.headRowNumber, this.clazz, this.password, this.type, this.filename);
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()) {
            return false;
        }
        final WriteMeta<?> writeMeta = (WriteMeta<?>) o;
        return Objects.equals(this.excelStream, writeMeta.excelStream) && Objects.equals(this.headRowNumber, writeMeta.headRowNumber) && Objects.equals(this.clazz, writeMeta.clazz) && Objects.equals(this.password, writeMeta.password) && this.type == writeMeta.type && Objects.equals(this.filename, writeMeta.filename);
    }

    /**
     * Gets excel stream.
     *
     * @return the excel stream
     */
    public OutputStream getExcelStream() {
        return this.excelStream;
    }

    /**
     * Sets excel stream.
     *
     * @param excelStream the excel stream
     */
    public void setExcelStream(final OutputStream excelStream) {
        this.excelStream = excelStream;
    }

    /**
     * Sets excel input data.
     *
     * @param excelInputData the excel input data
     */
    public void setExcelInputData(final OutputStream excelInputData) {
        this.excelStream = excelInputData;
    }

    /**
     * Gets head row number.
     *
     * @return the head row number
     */
    public Integer getHeadRowNumber() {
        return this.headRowNumber;
    }

    /**
     * Sets head row number.
     *
     * @param headRowNumber the head row number
     */
    public void setHeadRowNumber(final Integer headRowNumber) {
        this.headRowNumber = headRowNumber;
    }

    /**
     * Gets clazz.
     *
     * @return the clazz
     */
    public Class<T> getClazz() {
        return this.clazz;
    }

    /**
     * Sets clazz.
     *
     * @param clazz the clazz
     */
    public void setClazz(final Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * Gets password.
     *
     * @return the password
     */
    public String getPassword() {
        return this.password;
    }

    /**
     * Sets password.
     *
     * @param password the password
     */
    public void setPassword(final String password) {
        this.password = password;
    }

    /**
     * Gets type.
     *
     * @return the type
     */
    public ExcelTypeEnum getType() {
        return this.type;
    }

    /**
     * Sets type.
     *
     * @param type the type
     */
    public void setType(final ExcelTypeEnum type) {
        this.type = type;
    }

    /**
     * Gets filename.
     *
     * @return the filename
     */
    public String getFilename() {
        return this.filename;
    }

    /**
     * Sets filename.
     *
     * @param filename the filename
     */
    public void setFilename(final String filename) {
        this.filename = filename;
    }

    /**
     * Gets data.
     *
     * @return the data
     */
    public List<T> getData() {
        return this.data;
    }

    /**
     * Sets data.
     *
     * @param data the data
     */
    public void setData(final List<T> data) {
        this.data = data;
    }

    public static class Builder<T> {
        private OutputStream excelStream;
        private Integer headRowNumber;
        private Class<T> clazz;
        private String password;
        private List<T> data = new ArrayList<>();
        private ExcelTypeEnum type = ExcelTypeEnum.XLSX;
        private String filename = LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss");

        /**
         * Excel input data builder.
         *
         * @param excelStream the excel stream
         * @return the builder
         */
        public Builder<T> excelInputData(final OutputStream excelStream) {
            this.excelStream = excelStream;
            return this;
        }

        /**
         * Head row number builder.
         *
         * @param headRowNumber the head row number
         * @return the builder
         */
        public Builder<T> headRowNumber(final Integer headRowNumber) {
            this.headRowNumber = headRowNumber;
            return this;
        }

        /**
         * Clazz builder.
         *
         * @param clazz the clazz
         * @return the builder
         */
        public Builder<T> clazz(final Class<T> clazz) {
            this.clazz = clazz;
            return this;
        }

        /**
         * Password builder.
         *
         * @param password the password
         * @return the builder
         */
        public Builder<T> password(final String password) {
            this.password = password;
            return this;
        }

        /**
         * Data builder.
         *
         * @param data the data
         * @return the builder
         */
        public Builder<T> data(final List<T> data) {
            this.data = data;
            return this;
        }

        /**
         * Type builder.
         *
         * @param type the type
         * @return the builder
         */
        public Builder<T> type(final ExcelTypeEnum type) {
            this.type = type;
            return this;
        }

        /**
         * Filename builder.
         *
         * @param filename the filename
         * @return the builder
         */
        public Builder<T> filename(final String filename) {
            this.filename = filename;
            return this;
        }

        /**
         * Build write meta.
         *
         * @return the write meta
         */
        public WriteMeta<T> build() {
            return new WriteMeta<>(this);
        }
    }
}
